#include "Fdelphes.h"

std::ostream & operator<< (std::ostream & ostr, Jet* particle){
	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s %12s %12s %12s %12s %12s %12s\n", "px","py","pz","e","rapidity", "phi", "pt","m","btag","flavor"); // label the columns
	printf("%12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12i %12i\n",  particle->P4()[0], particle->P4()[1], particle->P4()[1], particle->P4()[2], particle->Eta,particle->Phi,particle->PT,particle->Mass,particle->BTag, particle->Flavor);
	std::cout<< "total contitents: " <<particle->Particles.GetEntriesFast() << std::endl;
	std::cout<< "contitents are: ";
	for( int consti_index = 0; consti_index < particle->Particles.GetEntriesFast(); consti_index++ )
	{
		TObject *object_jet = particle->Particles.At(consti_index);
		GenParticle *part = (GenParticle*) object_jet;
		std::cout<< part->PID <<" " ;
	}
	std::cout<<std::endl;
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, const std::vector<Jet*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%7s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s\n","jet #", "px","py","pz","e", "rapidity", "phi", "pt","m","btag", "flavor"); // label the columns
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%5u %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12i %12i\n", i, particles[i]->P4()[0], particles[i]->P4()[1], particles[i]->P4()[2], particles[i]->P4()[3], particles[i]->Eta,particles[i]->Phi,particles[i]->PT,particles[i]->Mass,particles[i]->BTag, particles[i]->Flavor);

	}
	return ostr;
}



std::ostream & operator<< (std::ostream & ostr, Electron* particle){
	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s  \n", "rapidity", "phi", "pt","charge"); // label the columns
	printf("%12.5f %12.5f %12.5f  %12i\n",  particle->Eta,particle->Phi,particle->PT,particle->Charge);
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, const std::vector<Electron*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%7s %12s %12s %12s %12s \n","Electron #",  "rapidity", "phi", "pt","charge"); // label the columns
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%5u %12.5f %12.5f %12.5f %12i\n", i,  particles[i]->Eta,particles[i]->Phi,particles[i]->PT,particles[i]->Charge);

	}
	return ostr;
}

std::ostream & operator<< (std::ostream & ostr, Muon* particle){
	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s  \n", "rapidity", "phi", "pt","charge"); // label the columns
	printf("%12.5f %12.5f %12.5f  %12i\n",  particle->Eta,particle->Phi,particle->PT,particle->Charge);
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, const std::vector<Muon*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%7s %12s %12s %12s %12s \n","Muon #",  "rapidity", "phi", "pt","charge"); // label the columns
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%5u %12.5f %12.5f %12.5f %12i\n", i,  particles[i]->Eta,particles[i]->Phi,particles[i]->PT,particles[i]->Charge);

	}
	return ostr;
}

std::ostream & operator<< (std::ostream & ostr, Photon* particle){
	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s  \n", "rapidity", "phi", "pt","E"); // label the columns
	printf("%12.5f %12.5f %12.5f  %12.5f\n",  particle->Eta,particle->Phi,particle->PT,particle->E);
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, const std::vector<Photon*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%7s %12s %12s %12s %12s \n","photon #",  "rapidity", "phi", "pt","E"); // label the columns
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%5u %12.5f %12.5f %12.5f %12.5f\n", i,  particles[i]->Eta,particles[i]->Phi,particles[i]->PT,particles[i]->E);

	}
	return ostr;
}


std::ostream & operator<< (std::ostream & ostr, MissingET* particle){
	printf("\n"); // label the columns
	printf("%12s %12s %12s \n", "rapidity", "phi", "MET"); // label the columns
	printf("%12.5f %12.5f %12.5f  \n",  particle->Eta,particle->Phi,particle->MET);
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, const std::vector<MissingET*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s  \n","MissingET #",  "rapidity", "phi", "pt"); // label the columns
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%12u %12.5f %12.5f %12.5f \n", i,  particles[i]->Eta,particles[i]->Phi,particles[i]->MET);

	}
	return ostr;
}


std::ostream & operator<<(std::ostream & ostr, GenParticle* particles){

	printf("\n"); // label the columns
	printf("%12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s \n",  "Status", "PID", "px","py","pz","e", "rapidity", "phi", "pt","m","father","mother","son","daughter"); // label the columns
	printf("%12i %12i %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12i %12i %12i %12i \n", particles->Status, particles->PID, particles->Px,particles->Py,particles->Pz,particles->E,particles->Eta,particles->Phi,particles->PT,particles->Mass,particles->M1,particles->M2,particles->D1,particles->D2);
	return ostr;
}

std::ostream & operator<<(std::ostream & ostr, const std::vector<GenParticle*> particles){

	if (particles.size() == 0) return ostr;

	printf("\n"); // label the columns
	printf("%7s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s %12s \n","particle #","Status", "PID", "px","py","pz","e", "rapidity", "phi", "pt","m","father","mother","son","daughter"); //  
	for (unsigned int i = 0; i < particles.size(); i++) {
		printf("%5u %12i %12i %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12.5f %12i %12i %12i %12i \n", i,particles[i]->Status, particles[i]->PID, particles[i]->Px,particles[i]->Py,particles[i]->Pz,particles[i]->E,particles[i]->Eta,particles[i]->Phi,particles[i]->PT,particles[i]->Mass,particles[i]->M1,particles[i]->M2,particles[i]->D1,particles[i]->D2);
	}
	return ostr;
}

bool DelphesJet_compare_PT(const Jet* a, const Jet* b)
{
	return a->PT > b->PT;
}
